﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Diagnostics;

namespace Fighter.Fights.Libraries
{
    public class Fight
    {
        public string ClubMail {get;set;}
        public int IDAthlete {get;set;}
        public int IDfight {get;set;}
        public int Age {get;set;}
        public Gender Gender{get;set;}
        public double Weight {get;set;}
        public Belts Belt {get;set;}
        public int NFight {get;set;}
        public string Classes {get;set;}
        public string AgeDesc { get; set; }
        public string WeightDesc { get; set; }
    }

    public class FightJoiner
    {
        XmlDocument xDoc = null;
        
        public string KeyResult { get; private set; }
        public SortedDictionary<string, Dictionary<string, Dictionary<int, Fight>>> FightJoin = new SortedDictionary<string, Dictionary<string, Dictionary<int, Fight>>>();

        int oldAge = 0;
        double oldWeight = 0.0;

        public FightJoiner()
        {
            xDoc = new XmlDocument();
            xDoc.LoadXml(Properties.Resources.Rules);
        }

        public void Clear()
        {
            FightJoin.Clear();
        }

        public void AddFight(string clubMail, int iDAthlete, int iDfight, int age, Gender gender, double weight, Belts belt, int nFight = 0, string classes = "")
        {
            oldAge = 0;
            oldWeight = 0.0;

            XmlNodeList xFights = xDoc.SelectNodes(string.Format("/rules/fight[@ID={0}]", iDfight));

            string ageDesc = string.Empty, weightDesc = string.Empty;

            KeyResult = CreateKey(xFights, age, gender, weight, belt, nFight, classes, ref ageDesc, ref weightDesc);

            Dictionary<string, Dictionary<int, Fight>> club = null;
            if (FightJoin.ContainsKey(KeyResult))
                club = FightJoin[KeyResult];
            else
            {
                club = new Dictionary<string, Dictionary<int, Fight>>();
                FightJoin.Add(KeyResult, club);
            }

            Dictionary<int, Fight> atlete = null;
            if (club.ContainsKey(clubMail))
                atlete = club[clubMail];
            else
            {
                atlete = new Dictionary<int, Fight>();
                club.Add(clubMail, atlete);
            }

            if (atlete.ContainsKey(iDAthlete))
                Debug.Assert(false);
            else
            {
                Fight match = new Fight()
                    {
                        ClubMail = clubMail,
                        IDAthlete = iDAthlete,
                        IDfight = iDfight,
                        Age = age,
                        Gender = gender,
                        Weight = weight,
                        Belt = belt,
                        NFight = nFight,
                        Classes = classes,
                        AgeDesc = ageDesc,
                        WeightDesc = weightDesc
                    };
                atlete.Add(iDAthlete, match);
            }
        }

        private string CreateKey(XmlNodeList xList, int age, Gender gender, double weight, Belts belt, int nFight, string classes, ref string  ageDesc, ref string weightDesc)
        {
            string key = "";
            foreach (XmlNode xRule in xList)
            {
                switch (xRule.Name)
                {
                    case "fight":
                        key = string.Format("[{0}:{1:00}]", xRule.Name, int.Parse(xRule.Attributes["ID"].Value));
                        if (xRule.HasChildNodes)
                            key += CreateKey(xRule.ChildNodes, age, gender, weight, belt, nFight, classes, ref ageDesc, ref weightDesc);
                        return key;
                        //break;
                    case "age":
                        int ageRange = int.Parse(xRule.Attributes["value"].Value);
                        if (ageRange >= age)
                        {
                            key = string.Format("[{0}:{1:00}]", xRule.Name, ageRange);
                            if (xRule.HasChildNodes)
                                key += CreateKey(xRule.ChildNodes, age, gender, weight, belt, nFight, classes, ref ageDesc, ref weightDesc);
                            ageDesc = CreateDescription(oldAge, ageRange, "Anni");
                            return key;
                        }
                        else
                            oldAge = ageRange;
                        break;
                    case "weight":
                        double weightrange = double.Parse(xRule.Attributes["value"].Value);
                        if (weightrange >= weight)
                        {
                            key = string.Format("[{0}:{1:000.0}]", xRule.Name, weightrange);
                            weightDesc = CreateDescription(oldWeight, weightrange, "Kg.");
                            return key;
                        }
                        else
                            oldWeight = weightrange;
                        break;
                    case "gender":
                        string sGender = gender.ToString().Substring(2,1).ToUpper();
                        if (xRule.Attributes["value"].Value == sGender)
                        {
                            key = string.Format("[{0}:{1}]", xRule.Name, xRule.Attributes["ID"].Value);
                            if (xRule.HasChildNodes)
                                key += CreateKey(xRule.ChildNodes, age, gender, weight, belt, nFight, classes, ref ageDesc, ref weightDesc);
                            return key;
                        }
                        break;
                    case "belt":
                        string sBelt = belt.ToString().Substring(2);
                        if (xRule.Attributes["value"].Value == sBelt)
                        {
                            key = string.Format("[{0}:{1}]", xRule.Name, xRule.Attributes["ID"].Value);
                            if (xRule.HasChildNodes)
                                key += CreateKey(xRule.ChildNodes, age, gender, weight, belt, nFight, classes, ref ageDesc, ref weightDesc);
                            return key;
                        }
                        break;
                    case "class":
                        if (xRule.Attributes["value"].Value == classes)
                        {
                            key = string.Format("[{0}:{1}]", xRule.Name, xRule.Attributes["ID"].Value);
                            if (xRule.HasChildNodes)
                                key += CreateKey(xRule.ChildNodes, age, gender, weight, belt, nFight, classes, ref ageDesc, ref weightDesc);
                            return key;
                        }
                        break;
                    case "series":
                        int fightrange = int.Parse(xRule.Attributes["value"].Value);
                        if (fightrange >= nFight)
                        {
                            key = string.Format("[{0}:{1}]", xRule.Name, xRule.Attributes["ID"].Value);
                            if (xRule.HasChildNodes)
                                key += CreateKey(xRule.ChildNodes, age, gender, weight, belt, nFight, classes, ref ageDesc, ref weightDesc);
                            return key;
                        }
                        break;
                }
            }
            return key;
        }

        private string CreateDescription(double oldWeight, double weightRange, string p)
        {
            if (oldWeight == 0.0)
                return string.Format("Fino a {0} {1}", weightRange, p);
            else
                if (weightRange == 300)
                    return string.Format("Oltre i {0} {1}", oldWeight, p);
                else
                    return string.Format("Da {0} a {1} {2}", oldWeight, weightRange, p);
        }

        private string CreateDescription(int olAge, int ageRange, string p)
        {
            if (olAge == 0.0)
                return string.Format("Fino a {0} {1}", ageRange, p);
            else
                if (ageRange == 99)
                    return string.Format("Oltre i {0} {1}", olAge, p);
                else
                    return string.Format("Da {0} a {1} {2}", olAge, ageRange, p);

        }
    }
}
